package com.example.demo.service.impl;

import com.example.demo.annotation.Collection;
import com.example.demo.core.MongoUtil;
import com.example.demo.pojo.*;
import com.example.demo.service.SubjectService;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Field;
import com.mongodb.client.model.Filters;
import com.mongodb.client.result.InsertOneResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.BsonDocument;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Consumer;

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.eq;

@Service("subjectServiceClientImpl")
public class SubjectServiceClientImpl implements SubjectService {

    private static final Log log = LogFactory.getLog(SubjectServiceClientImpl.class);

    @Autowired
    MongoUtil mongoUtil;


    @Override
    public void addSubject(Subject subject) {
        InsertOneResult result= mongoUtil.insetOne(subject,Subject.class);
        log.info(result);
    }

    @Override
    public void addTopicToSubject(String subjectId, Topic topic) {
        topic.setSubjectId(subjectId);
        InsertOneResult result= mongoUtil.insetOne(topic,Topic.class);
        log.info(result);
    }



    @Override
    public List<Topic> findBySubject(String subjectId){
        List<Topic> topics = new LinkedList<>();
        Bson bson =eq("subjectId",subjectId);
        topics =mongoUtil.find(bson,Topic.class);
        return topics;
    }

    @Override
    public void addTopicOptions(String topicId, TopicOption topicOption){
        topicOption.setTopicId(topicId);
        InsertOneResult result= mongoUtil.insetOne(topicOption,TopicOption.class);
        log.info(result);
    }

    @Override
    public void addAnswer(String oper, String topicId, String topicValue){
        Answer answer = new Answer();
        answer.setRegOper(oper);
        answer.setTopicId(topicId);
        answer.setTopicValue(topicValue);

        /*List<Topic> list = new ArrayList<>();
        mongoUtil.findConsumer(eq("_id",new ObjectId(topicId)), Topic.class,
                re ->{list.add(re);});*/
        List<Topic> list =mongoUtil.find(eq("_id",new ObjectId(topicId)),"topic_client",
                document -> {
                    Topic topic = new Topic();
                    topic.setSubjectId(document.get("subjectId",String.class));
                    topic.setName(document.get("name",String.class));
                    return topic;
                });
        if (CollectionUtils.isEmpty(list)){
            throw new RuntimeException("topic does not exits "+topicId);
        }else {
            Topic topic = list.get(0);
            answer.setSubjectId(topic.getSubjectId());
            mongoUtil.insetOne(answer,Answer.class);
        }

        /*Optional<Topic> optional=mongoOps.query(Topic.class)
                .matching(query(where("id").is(topicId))).first();
        if (optional.isPresent()){
            Topic topic = optional.get();
            answer.setSubjectId(topic.getSubjectId());
            mongoOps.insert(answer);
        }else {
            throw new RuntimeException("topic does not exits "+topicId);
        }*/

    }

    /**
     *
     * @param subjectId
     * @return
     */
    /*db.subject.aggregate([
    {$project:{id:{ $toString: '$_id' },title:1}},
    {
        $lookup:
        {
            from: "topic",
                    localField: "id",
                foreignField: "subjectId",
                as: "topics"
        }
    },
    {$unwind:"$topics"},
    {
        $project:{

            title:1,
                    topics:{
                id:{$toString: '$topics._id'} ,
                name:1,
                        type:1,
                        order:1
            }
        }
    },
    {
        $lookup:
        {
            from: "topicoption_client",
                    localField: "topics.id",
                foreignField: "topicId",
                as: "topics.topicOptions"
        }
    },
    {
        $group:{
            _id:   "$_id",
                    title:{$first:'$title'},
            topics:{$push:'$topics'}
        }
    }
    ])*/
    @Override
    public Document getQuestionnaire(String subjectId){
        List<Bson> pipeline=Arrays.asList(
                Aggregates.match(Filters.eq("_id", new ObjectId(subjectId))),
                Aggregates.project(new Document("id",new Document("$toString","$_id"))
                        .append("title",1)),
                Aggregates.lookup("topic_client","id","subjectId","topics"),
                Aggregates.unwind("$topics"),
                Aggregates.project(new Document("topics",new Document("id",new Document("$toString","$topics._id")).append("name",1).append("type",1).append("order",1))
                        .append("title",1)),
                Aggregates.lookup("topicoption_client","topics.id","topicId","topics.topicOptions"),
                Aggregates.group("$_id",Accumulators.push("topics","$topics"),Accumulators.first("title","$title"))
        );
        log.info(pipeline);
        Document re=mongoUtil.agg(pipeline,"subject_client");
        log.info(re);
        return re;
    }

   /* db.subject.aggregate([
    {$match:{_id:{$eq:ObjectId('5f363791badd872947095089')}}},
    {$addFields:{id:{ $toString: '$_id' }}},
    {
        $lookup:
        {
            from: "topic",
                    localField: "id",
                foreignField: "subjectId",
                as: "topics"
        }
    },
    {$unwind:"$topics"},
    {$addFields:{'topics.id':{ $toString: '$topics._id' }}},
    {
        $lookup:
        {
            from: "answer",
                    localField: "topics.id",
                foreignField: "topicId",
                as: "topics.answer"
        }
    }
    ])   ;*/
    @Override
    public List<Document> getQuestionnaireAnser(String subjectId){
        List<Bson> pipeline=Arrays.asList(
                Aggregates.match(Filters.eq("_id", new ObjectId(subjectId))),
                Aggregates.addFields(new Field<>("id",new Document("$toString","$_id"))),
                Aggregates.lookup("topic","id","subjectId","topics"),
                Aggregates.unwind("$topics"),
                Aggregates.addFields(new Field<>("topics.id",new Document("$toString","$topics._id"))),
                Aggregates.lookup("answer","topics.id","topicId","topics.answer"),
                Aggregates.group("$_id",Accumulators.first("title","$title"),
                                Accumulators.push("topics","$topics"))
        );
        log.info(pipeline);
        Document re=mongoUtil.agg(pipeline,"subject_client");
        log.info(re);
        List<Document> result=(List<Document>)re.get("result");
        return result;
    }

}
